﻿using Library.Collections.Generic;
using Library.Logic.Constraints;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using TRULE = System.Linq.Expressions.Expression<System.Func<System.Linq.IQueryable<System.Linq.Expressions.Expression>, System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression>>>>;
using TEXPRESSION = System.Linq.Expressions.Expression;

namespace Library.Linq.Expressions
{
    public abstract class LambdaExpression : Expression, IHasName<string>, IHasInputParameters, IHasOutputParameters, IHasPreconditionsReasonReadOnly, IHasPostconditionsReasonReadOnly, Library.Reflection.IPolymorphic<LambdaExpression>
    {
        internal LambdaExpression(Type delegateType, string name, bool tailCall, Expression body, IConstraintsReasonReadOnly preconditions, IConstraintsReasonReadOnly postconditions)
        {
            this.delegateType = delegateType;
            this.name = name;
            this.tailCall = tailCall;
            this.preconditions = preconditions;
            this.postconditions = postconditions;
            this.body = body;
        }

        Type delegateType;
        string name;
        bool tailCall;
        IConstraintsReasonReadOnly preconditions;
        IConstraintsReasonReadOnly postconditions;
        IConstraintsReasonReadOnly generatorconditions;
        Expression body;

        public string Name
        {
            get
            {
                return name;
            }
        }

        public IVectorReadOnly<ParameterExpression> InputParameters
        {
            get
            {
                return preconditions.InputParameters;
            }
        }

        public IVectorReadOnly<ParameterExpression> OutputParameters
        {
            get
            {
                return postconditions.InputParameters;
            }
        }

        public IVectorReadOnly<ParameterExpression> GeneratorParameters
        {
            get
            {
                return generatorconditions.InputParameters;
            }
        }
        
        public IConstraintsReasonReadOnly Preconditions
        {
            get
            {
                return preconditions;
            }
        }

        public IConstraintsReasonReadOnly Postconditions
        {
            get
            {
                return postconditions;
            }
        }

        public IConstraintsReasonReadOnly GeneratorPreconditions
        {
            get { throw new NotImplementedException(); }
        }

        public Expression Body
        {
            get
            {
                return body;
            }
        }

        public override Type Type
        {
            get
            {
                return delegateType;
            }
        }

        public Type ReturnType
        {
            get
            {
                return delegateType.GetMethod("Invoke").ReturnType;
            }
        }

        public bool TailCall
        {
            get
            {
                return tailCall;
            }
        }

        public override ExpressionType NodeType
        {
            get
            {
                return ExpressionType.Extension;
            }
        }

        public override bool CanReduce
        {
            get
            {
                return true;
            }
        }



        public bool IsGenerator
        {
            get { throw new NotImplementedException(); }
        }

        public Reflection.IGeneratorGroup<LambdaExpression, LambdaExpression> GeneratorGroup
        {
            get { throw new NotImplementedException(); }
        }

        public LambdaExpression Generate(object[] parameters)
        {
            throw new NotImplementedException();
        }

        public LambdaExpression Generator
        {
            get { throw new NotImplementedException(); }
        }

        public IVectorReadOnly<object> PolymorphicParameters
        {
            get { throw new NotImplementedException(); }
        }
    }
}
